#-*-coding:utf-8-*-
from math import *
'''
This module will calculate the Approximate Entropy!
@author:liuhucheng
15:40 05/09/2012
'''
class ApproEntr:
    '''
    This class can calculate the Approximate Entropy!
    '''
    def __init__(self):
        self.array = list()
        self.length = 0     #to record the length of the array

    def GenerateArrays(self,initvalue,lenth):
        '''
        this function will produce the array elements in order
        '''
        self.length = lenth
        i = 0
        self.array.append(initvalue)
        while(i < self.length):
            self.array.append(4.0 * self.array[i] * (1.0 -self.array[i]))
            #self.array.append(2.0 * self.array[i] / (1 - self.array[i]*self.array[i]))
            i += 1
        print 'Array is Created!'

    def CombineMvector(self,m = 2):
        '''
        This function will create m-dimensional vector
        '''
        combinelist = list()
        for i in range(self.length - m + 1):
            p = list()
            for j in range(m):
                p.append(self.array[i + j])
            #print p
            combinelist.append(p[:])
            #print combinelist
        print 'Create %d-dimensional vector is done!'%m
        #print combinelist
        return combinelist

    def calcDistance(self,CombineList,m = 2):
        '''
        calc the distance
        '''
        d = list()
        #print CombineList[0]
        for i in range(self.length - m + 1):
            dtemp = list()
            for j in range(self.length - m + 1):
                if j == i:
                    continue
                else:
                    #print j
                    dm = 0
                    for k in range(m):
                        #print k
                        pt = abs(CombineList[i][k] - CombineList[j][k])
                        if pt > dm:
                            dm = pt
                    dtemp.append(dm)
            #print i
            d.append(dtemp) #得到第三步所描述的矩阵序列
        print 'calcDistance Done!'
        return d

    def countItemR(self,d,r,m = 2):
        '''
        d为第三步求得的矩阵序列
        r 为阈值
        length为长度
        c为输出结果
        '''
        c = list()
        k = self.length - m
        print d
        print r
        for i in d:
            ci = 0
            for j in i:
                if j < r:
                    ci += 1
            c.append(float(ci)/(self.length - m))
        print 'counosttItemR Done!'
        return c

    def funm(self,c,m = 2):
        '''
        计算第五步
        '''
        kresult = 0
        #print c
        for i in c:
            #if i == 0:
                #i += 1
            kresult += (log(i))
        kresult = kresult / (self.length - m + 1)
        print 'funm Done!'
        return kresult

    def getEX(self):
        '''
        得到期望
        '''
        kresult = 0
        for i in self.array:
            kresult += i
        print 'getEX done!'
        return (kresult / self.length)

    def getR(self):
        '''
        得到方差和r
        '''
        u = self.getEX()
        kresult = 0
        for i in self.array:
            kresult += (pow((i - u),2))
        kresult = kresult / self.length
        a = sqrt(kresult)
        print 'getR Done!'
        #return 0.2*a
        return a

    def GetApproEntr(self,initvalue,lenth):
        '''
        to calculate the Approximate Entropy!
        '''
        self.__init__()     #clear the momery
        self.GenerateArrays(initvalue,lenth)    #generate the array
        combinelist2 = self.CombineMvector(2)
        #print combinelist2
        d2 = self.calcDistance(combinelist2,2)
        #print d2
        r = self.getR()
        #print r
        c2 = self.countItemR(d2,r,2)
        fun2 = self.funm(c2,2)

        #calc m+1=3
        combinelist3 = self.CombineMvector(3)
        d3 = self.calcDistance(combinelist3,3)
        c3 = self.countItemR(d3,r,3)
        fun3 = self.funm(c3,3)

        print fun2 - fun3

if __name__ == '__main__':
    c = ApproEntr()
    c.GetApproEntr(0.8,10)



